package org.lifxue.jqda.ui;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map.Entry;

import javax.swing.DefaultCellEditor;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.LayoutStyle;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.lifxue.jqda.jintellitype.GlobalHotkeyResourceManagement;
import org.lifxue.jqda.util.GlobalVar;

/**
 * 
 * @Description:
 * @Author: zhangzuoqiang
 * @Date: Sep 26, 2011
 */
public class HotKeyJDialog extends JDialog {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Log logger = LogFactory.getLog(HotKeyJDialog.class);
	private HashMap<String, String> HT_HOTKEY;
	private static HotKeyJDialog hotkey;

	public static HotKeyJDialog getInstance(boolean modal) {
		synchronized (HotKeyJDialog.class) {
			if (hotkey == null) {
				hotkey = new HotKeyJDialog(modal);
			}
		}
		return hotkey;
	}

	public HotKeyJDialog(boolean modal) {
		super(new JFrame(), modal);

		init();

		initComponents();

		initTableData();

		// 屏幕位置
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension frameSize = getSize();
		setLocation(new Point((screenSize.width - frameSize.width) / 2,
				(screenSize.height - frameSize.width) / 2));

	}

	/**
	 * Creates new form HotKeyJDialog
	 * 
	 * @param parent
	 * @param modal
	 */
	public HotKeyJDialog(java.awt.Frame parent, boolean modal) {
		super(parent, modal);
		initComponents();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {

		jScrollPane1 = new JScrollPane();
		hotKeyjTable = new JTable();
		addHotKeyjButton = new JButton();
		delHotKeyjButton = new JButton();
		jSeparator1 = new JSeparator();
		canceljButton = new JButton();
		okjButton = new JButton();

		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		setTitle("热键设置");

		jScrollPane1.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent evt) {
				jScrollPane1MouseClicked(evt);
			}
		});

		JTextField j = new JTextField();
		j.addKeyListener(keyAdapter);
		hotKeyjTable.setModel(new DefaultTableModel(new Object[][] {},
				new String[] { "标识", "组合键", "程序名称", "全路径" }) {

			private static final long serialVersionUID = 1L;
			Class<?>[] types = new Class[] { Integer.class, String.class,
					String.class, String.class };
			boolean[] canEdit = new boolean[] { false, true, false, false };

			public Class<?> getColumnClass(int columnIndex) {
				return types[columnIndex];
			}

			public boolean isCellEditable(int rowIndex, int columnIndex) {
				return canEdit[columnIndex];
			}
		});
		jScrollPane1.setViewportView(hotKeyjTable);
		hotKeyjTable.getColumnModel().getColumn(0).setMinWidth(35);
		hotKeyjTable.getColumnModel().getColumn(0).setPreferredWidth(35);
		hotKeyjTable.getColumnModel().getColumn(0).setMaxWidth(50);
		hotKeyjTable.getColumnModel().getColumn(1).setMinWidth(100);
		hotKeyjTable.getColumnModel().getColumn(1).setPreferredWidth(100);
		hotKeyjTable.getColumnModel().getColumn(1).setMaxWidth(120);
		hotKeyjTable.getColumnModel().getColumn(1)
				.setCellEditor(new TableEditor(j));
		hotKeyjTable.getColumnModel().getColumn(2).setMinWidth(80);
		hotKeyjTable.getColumnModel().getColumn(2).setPreferredWidth(80);
		hotKeyjTable.getColumnModel().getColumn(2).setMaxWidth(150);
		hotKeyjTable.getColumnModel().getColumn(3).setPreferredWidth(100);

		addHotKeyjButton.setText("增加热键");
		addHotKeyjButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				addHotKeyjButtonActionPerformed(evt);
			}
		});

		delHotKeyjButton.setText("删除热键");
		delHotKeyjButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				delHotKeyjButtonActionPerformed(evt);
			}
		});

		canceljButton.setText("取消");
		canceljButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				canceljButtonActionPerformed(evt);
			}
		});

		okjButton.setText("保存");
		okjButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				okjButtonActionPerformed(evt);
			}
		});

		GroupLayout layout = new GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addContainerGap()
																.addComponent(
																		jScrollPane1,
																		GroupLayout.DEFAULT_SIZE,
																		541,
																		Short.MAX_VALUE))
												.addGroup(
														layout.createSequentialGroup()
																.addGap(21, 21,
																		21)
																.addComponent(
																		addHotKeyjButton)
																.addGap(18, 18,
																		18)
																.addComponent(
																		delHotKeyjButton))
												.addGroup(
														layout.createSequentialGroup()
																.addContainerGap()
																.addComponent(
																		jSeparator1,
																		GroupLayout.DEFAULT_SIZE,
																		541,
																		Short.MAX_VALUE)))
								.addContainerGap())
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addContainerGap(411, Short.MAX_VALUE)
								.addComponent(okjButton).addGap(18, 18, 18)
								.addComponent(canceljButton).addGap(20, 20, 20)));
		layout.setVerticalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jScrollPane1,
										GroupLayout.PREFERRED_SIZE, 172,
										GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(addHotKeyjButton)
												.addComponent(delHotKeyjButton))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(jSeparator1,
										GroupLayout.PREFERRED_SIZE, 10,
										GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(canceljButton)
												.addComponent(okjButton))
								.addContainerGap(GroupLayout.DEFAULT_SIZE,
										Short.MAX_VALUE)));

		pack();
	}

	private void canceljButtonActionPerformed(ActionEvent evt) {
		// 系统热键
		GlobalHotkeyResourceManagement.initResources();
		GlobalHotkeyResourceManagement.addListener();

		closeEditing();
		setVisible(false);
		dispose();
		hotkey = null;
	}

	private void okjButtonActionPerformed(ActionEvent evt) {
		// int type = JOptionPane.CLOSED_OPTION;
		// String message = "重启后才能生效！";
		// JOptionPane.showConfirmDialog(this, message, "提示信息", type);
		closeEditing();
		GlobalVar.HOTKEY = HT_HOTKEY;

		canceljButtonActionPerformed(evt);
	}

	private void addHotKeyjButtonActionPerformed(ActionEvent evt) {
		closeEditing();
		// 建立文件选择框对象
		JFileChooser fc = new JFileChooser();
		fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		FileNameExtensionFilter filter = new FileNameExtensionFilter("可执行文件",
				"exe", "bat", "lnk");
		fc.setFileFilter(filter);

		// 设定文件选择框标题
		fc.setDialogTitle("选择可执行文件");
		// 显示文件选择框，在选择后将结果储存到returnVal变量中
		int returnVal = fc.showSaveDialog(this);
		// 如果用户选择了文件，并点击了"Opne/打开"按钮，显示用户选择的文件全名路径，
		// 如果用户点击"Close/关闭"按钮，以及其它方式退出文件选择框，则什么也不做。
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File file = fc.getSelectedFile();
			if (file == null) {
				return;
			}
			if (isExistPath(file)) {
				int type = JOptionPane.CLOSED_OPTION;
				String message = "你选择的文件已经在表格中了！";
				JOptionPane.showConfirmDialog(this, message, "提示信息", type);
				return;
			}
			Integer maxid = findMaxID() + 1;
			addTableRow(file, maxid);
			addOneHotKey(file, maxid);
		}
	}

	private void delHotKeyjButtonActionPerformed(ActionEvent evt) {
		closeEditing();
		DefaultTableModel model = (DefaultTableModel) hotKeyjTable.getModel();
		int allcount = model.getRowCount();
		int row = hotKeyjTable.getSelectedRow();
		if (row < 0) {
			return;
		}
		String filePath = model.getValueAt(row, 3).toString();
		model.removeRow(row);
		model.setRowCount(allcount - 1);

		HT_HOTKEY.remove(filePath);
	}

	private void jScrollPane1MouseClicked(MouseEvent evt) {
		closeEditing();
	}

	/**
	 * 关闭table的编辑状态
	 */
	private void closeEditing() {
		if (hotKeyjTable.isEditing()) {
			hotKeyjTable.getCellEditor().stopCellEditing();
		}
	}

	private void addOneHotKey(File file, Integer id) {
		String filePath = file.getPath();// 全路径
		String mod = id.toString();
		HT_HOTKEY.put(filePath, mod);
	}

	/**
	 * 在表格中增加一行数据
	 * 
	 * @param file
	 */
	private void addTableRow(File file, Integer id) {
		Object[] obj = new Object[4];
		obj[0] = id;
		obj[1] = "";
		obj[2] = file.getName().toLowerCase(Locale.CHINESE);
		obj[3] = file.getPath();
		((DefaultTableModel) hotKeyjTable.getModel()).addRow(obj);

	}

	private boolean isExistPath(File file) {
		boolean exist = false;
		DefaultTableModel model = (DefaultTableModel) hotKeyjTable.getModel();
		int allcount = model.getRowCount();
		for (int i = allcount - 1; i >= 0; i--) {
			Object temp = model.getValueAt(i, 3);
			if (temp.toString().equals(file.getPath())) {
				exist = true;
				break;
			}
		}
		return exist;
	}

	/**
	 * 从表格中找出最大标识
	 * 
	 * @return
	 */
	private Integer findMaxID() {
		Integer max = new Integer(0);

		DefaultTableModel model = (DefaultTableModel) hotKeyjTable.getModel();
		int allcount = model.getRowCount();
		for (int i = allcount - 1; i >= 0; i--) {
			Integer temp = (Integer) model.getValueAt(i, 0);
			if (temp > max) {
				max = temp;
			}
		}
		return max;
	}

	/**
	 * 初始化数据
	 */
	private void init() {
		HT_HOTKEY = GlobalVar.HOTKEY;
		GlobalHotkeyResourceManagement.removerListener();
		GlobalHotkeyResourceManagement.unregister();
	}

	/**
	 * 初始化表格数据
	 */
	private void initTableData() {
		DefaultTableModel model = (DefaultTableModel) hotKeyjTable.getModel();
		Iterator<Entry<String, String>> i = HT_HOTKEY.entrySet().iterator();
		while (i.hasNext()) {
			Object[] obj = new Object[4];
			String modkey = "";
			String fileName = "";

			Entry<String, String> entry = (Entry<String, String>) i.next();
			String key = (String) entry.getKey(); // 返回与此项对应的键
			String mod = (String) entry.getValue(); // 返回与此项对应的值

			String[] paths = key.split("\\\\");
			fileName = paths[paths.length - 1];
			String[] tempmod = mod.split(":");
			for (int l = 1; l < tempmod.length; l++) {
				modkey += tempmod[l] + "+";
			}
			if (modkey.indexOf("+") > -1) {
				modkey = modkey.substring(0, modkey.length() - 1);
			}
			obj[0] = tempmod[0];
			obj[1] = modkey;
			obj[2] = fileName;
			obj[3] = key;
			model.addRow(obj);
		}

	}

	private class TableEditor extends DefaultCellEditor {

		private static final long serialVersionUID = 1L;

		public TableEditor(JTextField j) {
			super(j);
		}

		@Override
		public boolean stopCellEditing() {
			String value = (String) getCellEditorValue();
			String[] tempmod = value.split("\\+");
			StringBuilder sb = new StringBuilder();
			for (int l = 0; l < tempmod.length - 1; l++) {
				sb.append(tempmod[l]);
				sb.append(":");
			}
			sb.append(tempmod[tempmod.length - 1]);

			boolean is = false;
			if ("Alt:Space".equals(sb.toString())) {// 调用主窗口的热键
				return false;
			}
			Iterator<Entry<String, String>> j = HT_HOTKEY.entrySet().iterator();
			while (j.hasNext()) {
				Entry<String, String> entry = (Entry<String, String>) j.next();
				String mod = (String) entry.getValue(); // 返回与此项对应的值
				int indexmod = mod.indexOf(":");
				String submod = "";
				if (indexmod > -1) {
					submod = mod.substring(indexmod + 1);
				}
				if (submod.equals(sb.toString())) {
					is = true;
					break;
				}

			}
			if (is) {
				return false;
			}

			try {
				// 保存组合键信息到数组中
				DefaultTableModel model = (DefaultTableModel) hotKeyjTable
						.getModel();
				int selectedid = hotKeyjTable.getSelectedRow();
				String filePath = model.getValueAt(selectedid, 3).toString();
				Iterator<Entry<String, String>> i = HT_HOTKEY.entrySet()
						.iterator();
				while (i.hasNext()) {
					Entry<String, String> entry = (Entry<String, String>) i
							.next();
					String key = (String) entry.getKey(); // 返回与此项对应的键
					String mod = (String) entry.getValue(); // 返回与此项对应的值
					String submod = mod;
					int indexmod = mod.indexOf(":");
					if (indexmod > -1) {
						submod = mod.substring(0, indexmod);
					}
					if (key.equals(filePath)) {
						for (int l = 0; l < tempmod.length; l++) {
							submod += ":" + tempmod[l];
						}
						HT_HOTKEY.put(key, submod);
						break;
					}
				}

			} catch (NumberFormatException e) {
				logger.debug(e);
			}
			return super.stopCellEditing();
		}
	}

	private KeyAdapter keyAdapter = new KeyAdapter() {

		@Override
		public void keyPressed(KeyEvent e) {
			// 按下ctrl
			if (e.isControlDown()) {
				String modifiers = KeyEvent.getKeyModifiersText(e
						.getModifiers());
				String text = KeyEvent.getKeyText(e.getKeyCode());
				((JTextField) e.getComponent()).setText(modifiers + "+" + text);
			} else if (e.isAltDown()) {
				String modifiers = KeyEvent.getKeyModifiersText(e
						.getModifiers());
				String text = KeyEvent.getKeyText(e.getKeyCode());
				((JTextField) e.getComponent()).setText(modifiers + "+" + text);
			}
		}
	};

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				HotKeyJDialog dialog = new HotKeyJDialog(new JFrame(), true);
				dialog.addWindowListener(new WindowAdapter() {

					@Override
					public void windowClosing(WindowEvent e) {
						System.exit(0);
					}
				});
				dialog.setVisible(true);
			}
		});
	}

	private JButton addHotKeyjButton;
	private JButton canceljButton;
	private JButton delHotKeyjButton;
	private JTable hotKeyjTable;
	private JScrollPane jScrollPane1;
	private JSeparator jSeparator1;
	private JButton okjButton;
}
